package com.mask.token.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.HashMap;
import java.util.Map;

/**
 * Token健康检查服务
 * 提供系统健康状态监控
 *
 * @author mask
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
@ConditionalOnProperty(name = "mask.token.health.enabled", havingValue = "true", matchIfMissing = false)
public class MaskTokenHealthService {

    private final MaskTokenService tokenService;
    private final MaskTokenRedisService redisService;

    /**
     * 获取健康状态
     */
    public HealthStatus getHealthStatus() {
        try {
            HealthStatus status = new HealthStatus();
            status.setTimestamp(Instant.now());
            status.setOverallStatus("UP");
            
            Map<String, Object> details = new HashMap<>();
            
            // 检查Token服务状态
            boolean tokenServiceHealthy = checkTokenServiceHealth();
            details.put("tokenService", tokenServiceHealthy ? "UP" : "DOWN");
            
            // 检查Redis连接状态
            boolean redisHealthy = checkRedisHealth();
            details.put("redis", redisHealthy ? "UP" : "DOWN");
            
            // 检查内存使用情况
            MemoryInfo memoryInfo = getMemoryInfo();
            details.put("memory", memoryInfo);
            
            // 检查Token统计
            TokenHealthInfo tokenHealth = getTokenHealthInfo();
            details.put("tokens", tokenHealth);
            
            // 检查系统负载
            SystemLoadInfo systemLoad = getSystemLoadInfo();
            details.put("systemLoad", systemLoad);
            
            // 确定整体健康状态
            if (!tokenServiceHealthy || !redisHealthy) {
                status.setOverallStatus("DOWN");
            } else if (memoryInfo.getUsagePercentage() > 90 || systemLoad.getCpuUsage() > 90) {
                status.setOverallStatus("WARNING");
            }
            
            status.setDetails(details);
            return status;
            
        } catch (Exception e) {
            log.error("健康检查失败", e);
            HealthStatus status = new HealthStatus();
            status.setOverallStatus("DOWN");
            status.setTimestamp(Instant.now());
            Map<String, Object> errorDetails = new HashMap<>();
            errorDetails.put("error", e.getMessage());
            status.setDetails(errorDetails);
            return status;
        }
    }

    /**
     * 检查Token服务健康状态
     */
    private boolean checkTokenServiceHealth() {
        try {
            // 尝试生成一个测试Token
            String testToken = tokenService.generateAccessToken(createTestUserDetails());
            boolean isValid = tokenService.validateToken(testToken);
            tokenService.logout(testToken);
            return isValid;
        } catch (Exception e) {
            log.warn("Token服务健康检查失败", e);
            return false;
        }
    }

    /**
     * 检查Redis健康状态
     */
    private boolean checkRedisHealth() {
        try {
            String redisInfo = tokenService.getRedisInfo();
            return redisInfo != null && !redisInfo.contains("Redis不可用");
        } catch (Exception e) {
            log.warn("Redis健康检查失败", e);
            return false;
        }
    }

    /**
     * 获取内存使用信息
     */
    private MemoryInfo getMemoryInfo() {
        Runtime runtime = Runtime.getRuntime();
        long totalMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        long usedMemory = totalMemory - freeMemory;
        long maxMemory = runtime.maxMemory();
        
        double usagePercentage = (double) usedMemory / maxMemory * 100;
        
        MemoryInfo info = new MemoryInfo();
        info.setTotalMemory(totalMemory);
        info.setUsedMemory(usedMemory);
        info.setFreeMemory(freeMemory);
        info.setMaxMemory(maxMemory);
        info.setUsagePercentage(usagePercentage);
        
        return info;
    }

    /**
     * 获取Token健康信息
     */
    private TokenHealthInfo getTokenHealthInfo() {
        try {
            TokenHealthInfo info = new TokenHealthInfo();
            
            // 获取在线用户数（这里需要实际实现）
            info.setOnlineUsers(0);
            info.setTotalTokens(0);
            info.setExpiredTokens(0);
            info.setTokenGenerationRate(0.0);
            
            return info;
        } catch (Exception e) {
            log.warn("获取Token健康信息失败", e);
            return new TokenHealthInfo();
        }
    }

    /**
     * 获取系统负载信息
     */
    private SystemLoadInfo getSystemLoadInfo() {
        SystemLoadInfo info = new SystemLoadInfo();
        
        // 获取CPU使用率（这里需要实际实现）
        info.setCpuUsage(0.0);
        info.setLoadAverage(0.0);
        info.setThreadCount(Thread.activeCount());
        
        return info;
    }

    /**
     * 创建测试用户详情
     */
    private com.mask.token.model.MaskUserDetails createTestUserDetails() {
        com.mask.token.model.MaskUserDetails userDetails = new com.mask.token.model.MaskUserDetails();
        userDetails.setUserId(999L);
        userDetails.setUsername("health-check-user");
        userDetails.setPassword("test");
        userDetails.setDeviceId("health-check-device");
        return userDetails;
    }

    /**
     * 内存信息
     */
    public static class MemoryInfo {
        private long totalMemory;
        private long usedMemory;
        private long freeMemory;
        private long maxMemory;
        private double usagePercentage;

        // Getters and Setters
        public long getTotalMemory() { return totalMemory; }
        public void setTotalMemory(long totalMemory) { this.totalMemory = totalMemory; }
        public long getUsedMemory() { return usedMemory; }
        public void setUsedMemory(long usedMemory) { this.usedMemory = usedMemory; }
        public long getFreeMemory() { return freeMemory; }
        public void setFreeMemory(long freeMemory) { this.freeMemory = freeMemory; }
        public long getMaxMemory() { return maxMemory; }
        public void setMaxMemory(long maxMemory) { this.maxMemory = maxMemory; }
        public double getUsagePercentage() { return usagePercentage; }
        public void setUsagePercentage(double usagePercentage) { this.usagePercentage = usagePercentage; }
    }

    /**
     * Token健康信息
     */
    public static class TokenHealthInfo {
        private int onlineUsers;
        private int totalTokens;
        private int expiredTokens;
        private double tokenGenerationRate;

        // Getters and Setters
        public int getOnlineUsers() { return onlineUsers; }
        public void setOnlineUsers(int onlineUsers) { this.onlineUsers = onlineUsers; }
        public int getTotalTokens() { return totalTokens; }
        public void setTotalTokens(int totalTokens) { this.totalTokens = totalTokens; }
        public int getExpiredTokens() { return expiredTokens; }
        public void setExpiredTokens(int expiredTokens) { this.expiredTokens = expiredTokens; }
        public double getTokenGenerationRate() { return tokenGenerationRate; }
        public void setTokenGenerationRate(double tokenGenerationRate) { this.tokenGenerationRate = tokenGenerationRate; }
    }

    /**
     * 系统负载信息
     */
    public static class SystemLoadInfo {
        private double cpuUsage;
        private double loadAverage;
        private int threadCount;

        // Getters and Setters
        public double getCpuUsage() { return cpuUsage; }
        public void setCpuUsage(double cpuUsage) { this.cpuUsage = cpuUsage; }
        public double getLoadAverage() { return loadAverage; }
        public void setLoadAverage(double loadAverage) { this.loadAverage = loadAverage; }
        public int getThreadCount() { return threadCount; }
        public void setThreadCount(int threadCount) { this.threadCount = threadCount; }
    }

    /**
     * 健康状态
     */
    public static class HealthStatus {
        private String overallStatus;
        private Instant timestamp;
        private Map<String, Object> details;

        // Getters and Setters
        public String getOverallStatus() { return overallStatus; }
        public void setOverallStatus(String overallStatus) { this.overallStatus = overallStatus; }
        public Instant getTimestamp() { return timestamp; }
        public void setTimestamp(Instant timestamp) { this.timestamp = timestamp; }
        public Map<String, Object> getDetails() { return details; }
        public void setDetails(Map<String, Object> details) { this.details = details; }
    }
}
